package org.geektimes.web.mvc.header.matedata;

import org.geektimes.base.util.ReflectionUtils;
import org.geektimes.web.mvc.header.*;
import org.geektimes.web.mvc.header.annotation.BodyParam;
import org.geektimes.web.mvc.header.annotation.HeadParam;
import org.geektimes.web.mvc.header.annotation.Param;
import org.geektimes.web.mvc.header.annotation.QueryParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;


/**
* 参数信息  
* @author : KangNing Hu
*/
public class ParamInfo {



	public static final ParamParse HEAD_PARAM_PARSE_INSTANCE = new HeadParamParse();

	public static final ParamParse BODY_PARAM_PARSE_INSTANCE = new BodyParamParse();

	public static final ParamParse QUERY_PARAM_PARSE_INSTANCE = new QueryParamParse();

	public static  final ParamParse DEFAULT_PARAM_PARSE_INSTANCE = new DefaultParamParse();

	public static final ParamParse EMPTY_PARAM_PARSE_INSTANCE = new EmptyParamParse();

	/**
	 * 参数类型
	 */
	private Type type;


	/**
	 * 字段对象列表
	 */
	private List<Field> fields;

	/**
	 * 参数的注解
	 */
	private Annotation[] annotations;

	/**
	 * 参数在方法中的索引
	 */
	private int index;

	/**
	 * 参数名称
	 */
	private String name;

	/**
	 * 参数类型
	 */
	private ParamType paramType;

	/**
	 * 参数解析器
	 */
	private ParamParse paramParse;

	public ParamInfo(Type type , int index , Annotation[] annotations){
		this.annotations = annotations;
		this.index = index;
		this.type = type;
		init();
	}

	/**
	 * 初始化
	 */
	private void init() {

		if (type instanceof ParameterizedType){
			this.type = ((ParameterizedType) type).getRawType();
		}
		if (!ReflectionUtils.isGeneralType((Class) type)){
			this.fields = ReflectionUtils.getFields((Class) type , Object.class);
		}
		//TODO 可以改为动态匹配 参数解析器的策略实现动态插拔
		//处理缺省参数 如：HttpServletRequest, HttpServletResponse
		if (isDefaultParam((Class) this.type)){
			paramParse = DEFAULT_PARAM_PARSE_INSTANCE;
		}else {
			for (Annotation annotation : annotations) {
				Class<? extends Annotation> annotationType = annotation.annotationType();
				Param param = annotationType.getAnnotation(Param.class);
				if (param != null) {
					this.paramType = param.value();
				}
				if (annotationType == BodyParam.class) {
					this.paramParse = BODY_PARAM_PARSE_INSTANCE;
				} else if (annotationType == HeadParam.class) {
					HeadParam headParam = (HeadParam) annotation;
					this.name = headParam.value();
					this.paramParse = HEAD_PARAM_PARSE_INSTANCE;
				} else if (annotationType == QueryParam.class) {
					QueryParam queryParam = (QueryParam) annotation;
					this.name = queryParam.value();
					this.paramParse = QUERY_PARAM_PARSE_INSTANCE;
				}
			}
		}
		if (this.paramParse == null){
			this.paramParse = EMPTY_PARAM_PARSE_INSTANCE;
		}
	}



	public List<Field> getFields() {
		return fields;
	}


	public ParamParse getParamParse() {
		return paramParse;
	}


	public Class getType() {
		return (Class) type;
	}


	public int getIndex() {
		return index;
	}



	public String getName() {
		return name;
	}

	public ParamType getParamType() {
		return paramType;
	}


	/**
	 * 判断是否是缺省参数
	 * @param clazz 参数类型class
	 * @return
	 */
	private boolean isDefaultParam(Class clazz){
		return clazz == HttpServletRequest.class
				||clazz == HttpServletResponse.class
				||clazz == WebContent.class;
	}

	public enum ParamType{
		QUERY,BODY,HEAD
	}

}
